package cn.thr.ymcc.service.impl;

import cn.thr.ymcc.client.LogininfoClient;
import cn.thr.ymcc.domain.*;
import cn.thr.ymcc.dto.RegDto;
import cn.thr.ymcc.mapper.UserBaseInfoMapper;
import cn.thr.ymcc.mapper.UserGrowLogMapper;
import cn.thr.ymcc.mapper.UserMapper;
import cn.thr.ymcc.mapper.UserRealInfoMapper;
import cn.thr.ymcc.result.JsonResult;
import cn.thr.ymcc.service.IUserService;
import cn.thr.ymcc.util.AssertUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * <p>
 * 会员登录账号 服务实现类
 * </p>
 *
 * @author thr
 * @since 2023-02-26
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;
    @Autowired
    private LogininfoClient logininfoClient;

    @Autowired
    private UserBaseInfoMapper userBaseInfoMapper;

    @Autowired
    private UserRealInfoMapper userRealInfoMapper;


    @Autowired
    private UserGrowLogMapper userGrowLogMapper;
    /**
     * 前台用户注册
     * @param regDto
     * @return
     */
    //@Transactional是spring中声明式事务管理的注解配置方式
    //@Transactional注解可以帮助我们把事务开启、提交或者回滚的操作,通过aop的方式进行管理
    @GlobalTransactional(rollbackFor = Exception.class)
    @Override
    public void register(RegDto regDto) {
        //1.手机号必须没有被注册
        User phone = baseMapper.selectOne(new QueryWrapper<User>().eq("phone", regDto.getMobile()));
        //判断手机号是否注册
        AssertUtil.isTrue(phone == null ,"手机号已经被注册");

        //2.检验手机验证码
        //判断验证码是否过期
        AssertUtil.isTrue(redisTemplate.hasKey(regDto.getMobile()),"短信验证码已过期！");
        //判断验证码是否正确    输入的验证码和从数据库里面取出来的验证码做对比
        AssertUtil.isTrue(regDto.getSmsCode().equals(redisTemplate.opsForValue().get(regDto.getMobile())),"验证码错误哦！");

        //3。调用openfeign 调用认证中心的接口 保存用户信息
        Login login = new Login()
                //getMobile 手机号就相当于用户名
                .setUsername(regDto.getMobile())
                //密码加密 BCryptPasswordEncoder
                .setPassword(new BCryptPasswordEncoder().encode(regDto.getPassword()))
                //设置状态
                .setType(1);
        //执行添加方法，把regDto 的数据添加到login 表里面
        JsonResult jsonResult = logininfoClient.saveOrUpdate(login);
        //判断是是否成功 成功就报操作成功
        AssertUtil.isTrue(jsonResult.getSuccess(),jsonResult.getMessage());

        //使用openfeign调用三方接口：三方接口返回的值是Long，但经过openfeign后，变成了Integer
        Long loginid = Long.valueOf(jsonResult.getData().toString());

        //4.保存数据
        User user = new User()
                .setPhone(regDto.getMobile())
                .setNickName(regDto.getMobile())
                .setLoginId(loginid);

        //由于单表操作无需写SQL，mybatisplus不确定你到底需不需要返回主键，只要insert数据都会返回主键
        baseMapper.insert(user);


        //5.用户的基本信息
        UserBaseInfo userBaseInfo = new UserBaseInfo()
                .setRegChannel(regDto.getRegChannel())
                .setUserId(user.getId());
        userBaseInfoMapper.insert(userBaseInfo);

        //6.用户实名认证
        UserRealInfo userRealInfo = new UserRealInfo()
                .setUserId(user.getId());
        userRealInfoMapper.insert(userRealInfo);

        //7.注册送积分：建议使用properties文件或者一张表来维护每个操作送多少积分
        UserGrowLog userGrowLog = new UserGrowLog()
                .setUserId(user.getId())
                .setFromReason("新用户注册")
                .setScore(50);
        userGrowLogMapper.insert(userGrowLog);
    }
}
